"""
认证服务
创建时间：2025-09-12
作者：开发团队
目的：处理用户认证相关业务逻辑
"""

from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
from datetime import datetime
from ..models.user import User
from ..core.security import get_password_hash
from ..utils.logger import get_logger

# 获取日志记录器
logger = get_logger(__name__)


def get_user_by_username(db: Session, username: str) -> User | None:
    """
    根据用户名获取用户
    :param db: 数据库会话
    :param username: 用户名
    :return: 用户对象或None
    """
    try:
        user = db.query(User).filter(User.username == username).first()
        return user
    except SQLAlchemyError as e:
        logger.error(f"查询用户失败: {str(e)}")
        return None


def get_user_by_id(db: Session, user_id: int) -> User | None:
    """
    根据用户ID获取用户
    :param db: 数据库会话
    :param user_id: 用户ID
    :return: 用户对象或None
    """
    try:
        user = db.query(User).filter(User.id == user_id).first()
        return user
    except SQLAlchemyError as e:
        logger.error(f"查询用户失败: {str(e)}")
        return None


def create_user(db: Session, username: str, password: str, name: str, role: str, 
                phone: str | None = None, campus_id: int | None = None) -> User | None:
    """
    创建新用户
    :param db: 数据库会话
    :param username: 用户名
    :param password: 密码
    :param name: 姓名
    :param role: 角色
    :param phone: 手机号
    :param campus_id: 院区ID
    :return: 用户对象或None
    """
    try:
        # 检查用户名是否已存在
        existing_user = get_user_by_username(db, username)
        if existing_user:
            logger.warning(f"用户名已存在: {username}")
            return None
        
        # 创建用户对象
        user = User(
            username=username,
            password_hash=get_password_hash(password),
            name=name,
            role=role,
            phone=phone,
            campus_id=campus_id
        )
        
        # 保存到数据库
        db.add(user)
        db.commit()
        db.refresh(user)
        
        logger.info(f"用户创建成功: {username}")
        return user
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"创建用户失败: {str(e)}")
        return None


def update_last_login(db: Session, user_id: int, login_time: datetime) -> bool:
    """
    更新用户最后登录时间
    :param db: 数据库会话
    :param user_id: 用户ID
    :param login_time: 登录时间
    :return: 是否更新成功
    """
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if user:
            setattr(user, 'last_login', login_time)
            db.commit()
            return True
        return False
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"更新最后登录时间失败: {str(e)}")
        return False


def update_user_profile(db: Session, user_id: int, name: str | None = None, 
                       phone: str | None = None) -> User | None:
    """
    更新用户资料
    :param db: 数据库会话
    :param user_id: 用户ID
    :param name: 姓名
    :param phone: 手机号
    :return: 用户对象或None
    """
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user:
            return None
        
        if name is not None:
            setattr(user, 'name', name)
        if phone is not None:
            setattr(user, 'phone', phone)
            
        db.commit()
        db.refresh(user)
        
        logger.info(f"用户资料更新成功: {user.username}")
        return user
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"更新用户资料失败: {str(e)}")
        return None


def change_user_password(db: Session, user_id: int, new_password: str) -> bool:
    """
    修改用户密码
    :param db: 数据库会话
    :param user_id: 用户ID
    :param new_password: 新密码
    :return: 是否修改成功
    """
    try:
        user = db.query(User).filter(User.id == user_id).first()
        if not user:
            return False
        
        setattr(user, 'password_hash', get_password_hash(new_password))
        db.commit()
        
        logger.info(f"用户密码修改成功: {user.username}")
        return True
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"修改用户密码失败: {str(e)}")
        return False